import Foundation
import CoreLocation
import CommonCrypto

// MARK: - 腾讯地图API服务
class TencentMapsService {
    static let shared = TencentMapsService()
    
    private var apiKey: String {
        return GeocodingConfig.shared.tencentApiKey
    }
    
    private var secretKey: String {
        return GeocodingConfig.shared.tencentSecretKey
    }
    
    private let baseURL = "https://apis.map.qq.com/ws"
    private let timeoutInterval: TimeInterval = 15.0
    
    private init() {}
    
    // MARK: - 逆向地理编码（坐标转地址）
    func reverseGeocode(coordinate: CLLocationCoordinate2D) async -> GlobalLocationAddressInfo? {
        let urlString = "\(baseURL)/geocoder/v1/?key=\(apiKey)&location=\(coordinate.latitude),\(coordinate.longitude)&get_poi=1"
        
        guard let url = URL(string: urlString) else {
            print("🗺️ [Tencent] 无效URL: \(urlString)")
            return nil
        }
        
        var request = URLRequest(url: url)
        request.timeoutInterval = timeoutInterval
        
        do {
            let (data, response) = try await URLSession.shared.data(for: request)
            
            guard let httpResponse = response as? HTTPURLResponse else {
                print("🗺️ [Tencent] 无效HTTP响应")
                return nil
            }
            
            print("🗺️ [Tencent] 逆向地理编码响应状态: \(httpResponse.statusCode)")
            
            if httpResponse.statusCode == 200 {
                let result = try JSONDecoder().decode(TencentGeocodeResponse.self, from: data)
                
                if result.status == 0 {
                    guard let result = result.result else {
                        print("🗺️ [Tencent] 逆向地理编码失败: 无地址信息")
                        return nil
                    }
                    
                    let addressComponent = result.addressComponent
                    let formattedAddress = result.formattedAddresses?.recommend ?? result.formattedAddresses?.regular ?? ""
                    
                    let addressInfo = GlobalLocationAddressInfo(
                        country: addressComponent.nation,
                        province: addressComponent.province,
                        city: addressComponent.city,
                        district: addressComponent.district,
                        township: addressComponent.town,
                        street: addressComponent.street,
                        poiName: result.pois?.first?.title,
                        formattedAddress: formattedAddress
                    )
                    
                    print("🗺️ [Tencent] 逆向地理编码成功: \(coordinate) -> \(formattedAddress)")
                    return addressInfo
                } else {
                    print("🗺️ [Tencent] 逆向地理编码失败: \(result.message)")
                }
            } else {
                print("🗺️ [Tencent] HTTP错误: \(httpResponse.statusCode)")
            }
        } catch {
            print("🗺️ [Tencent] 逆向地理编码异常: \(error)")
        }
        
        return nil
    }
    
    // MARK: - 带签名的逆向地理编码（使用签名验证）
    func reverseGeocodeWithSignature(coordinate: CLLocationCoordinate2D) async -> GlobalLocationAddressInfo? {
        // 构建签名参数（与test_tencent.swift保持一致）
        let params = [
            "key": apiKey,
            "location": "\(coordinate.latitude),\(coordinate.longitude)",
            "get_poi": "1"
        ]
        
        // 1. 参数排序
        let sortedParams = params.sorted { $0.key < $1.key }
        // 2. 拼接参数串
        let paramString = sortedParams.map { "\($0.key)=\($0.value)" }.joined(separator: "&")
        // 3. 拼接签名串
        let signString = "/ws/geocoder/v1?" + paramString + secretKey
        // 4. 生成签名
        guard let data = signString.data(using: .utf8) else {
            print("🗺️ [Tencent] 签名字符串编码失败")
            return nil
        }
        let length = Int(CC_MD5_DIGEST_LENGTH)
        var digest = [UInt8](repeating: 0, count: length)
        _ = data.withUnsafeBytes { body in
            CC_MD5(body.baseAddress, CC_LONG(data.count), &digest)
        }
        let signature = digest.map { String(format: "%02hhx", $0) }.joined()
        
        // 调试信息
        print("🗺️ [Tencent] 排序后参数: \(sortedParams)")
        print("🗺️ [Tencent] 参数串: \(paramString)")
        print("🗺️ [Tencent] 签名字符串: \(signString)")
        print("🗺️ [Tencent] MD5结果: \(signature)")
        
        // 5. 构建URL（顺序和签名完全一致，sig放最后）
        let urlParamString = paramString + "&sig=\(signature)"
        let urlString = "\(baseURL)/geocoder/v1?\(urlParamString)"
        print("🗺️ [Tencent] 完整URL: \(urlString)")
        
        guard let url = URL(string: urlString) else {
            print("🗺️ [Tencent] 无效URL: \(urlString)")
            return nil
        }
        
        var request = URLRequest(url: url)
        request.timeoutInterval = timeoutInterval
        
        do {
            let (data, response) = try await URLSession.shared.data(for: request)
            
            guard let httpResponse = response as? HTTPURLResponse else {
                print("🗺️ [Tencent] 无效HTTP响应")
                return nil
            }
            
            print("🗺️ [Tencent] 带签名的逆向地理编码响应状态: \(httpResponse.statusCode)")
            
            if httpResponse.statusCode == 200 {
                // 打印原始响应内容用于调试
                if let responseString = String(data: data, encoding: .utf8) {
                    print("🗺️ [Tencent] 原始响应内容: \(responseString)")
                }
                
                let result = try JSONDecoder().decode(TencentGeocodeResponse.self, from: data)
                
                if result.status == 0 {
                    guard let result = result.result else {
                        print("🗺️ [Tencent] 逆向地理编码失败: 无地址信息")
                        return nil
                    }
                    
                    let addressComponent = result.addressComponent
                    let formattedAddress = result.formattedAddresses?.recommend ?? result.formattedAddresses?.regular ?? ""
                    
                    let addressInfo = GlobalLocationAddressInfo(
                        country: addressComponent.nation,
                        province: addressComponent.province,
                        city: addressComponent.city,
                        district: addressComponent.district,
                        township: addressComponent.town,
                        street: addressComponent.street,
                        poiName: result.pois?.first?.title,
                        formattedAddress: formattedAddress
                    )
                    
                    print("🗺️ [Tencent] 带签名的逆向地理编码成功: \(coordinate) -> \(formattedAddress)")
                    return addressInfo
                } else {
                    print("🗺️ [Tencent] 逆向地理编码失败: \(result.message)")
                }
            } else {
                print("🗺️ [Tencent] HTTP错误: \(httpResponse.statusCode)")
            }
        } catch {
            print("🗺️ [Tencent] 逆向地理编码异常: \(error)")
        }
        
        return nil
    }
    
    // MARK: - 生成签名
    private func generateSignature(params: [String: String], secretKey: String) -> String {
        // 按参数名排序
        let sortedParams = params.sorted { $0.key < $1.key }
        
        // 拼接参数串（未编码）
        let paramString = sortedParams.map { "\($0.key)=\($0.value)" }.joined(separator: "&")
        
        // 拼接签名串（使用正确的路径格式）
        let signString = "/ws/geocoder/v1?" + paramString + secretKey
        
        // 调试信息
        print("🗺️ [Tencent] 排序后参数: \(sortedParams)")
        print("🗺️ [Tencent] 参数串: \(paramString)")
        print("🗺️ [Tencent] 签名字符串: \(signString)")
        
        // 使用Data的MD5计算方法（与test_tencent.swift保持一致）
        guard let data = signString.data(using: .utf8) else {
            print("🗺️ [Tencent] 签名字符串编码失败")
            return ""
        }
        
        let length = Int(CC_MD5_DIGEST_LENGTH)
        var digest = [UInt8](repeating: 0, count: length)
        _ = data.withUnsafeBytes { body in
            CC_MD5(body.baseAddress, CC_LONG(data.count), &digest)
        }
        let md5Result = digest.map { String(format: "%02hhx", $0) }.joined()
        print("🗺️ [Tencent] MD5结果: \(md5Result)")
        return md5Result
    }
}

// MARK: - 腾讯地图API响应模型
struct TencentGeocodeResponse: Codable {
    let status: Int
    let message: String
    let result: TencentGeocodeResult?
}

struct TencentGeocodeResult: Codable {
    let address_component: TencentAddressComponent
    let formatted_addresses: TencentFormattedAddresses?
    let pois: [TencentPOI]?
    
    // 计算属性，保持向后兼容
    var addressComponent: TencentAddressComponent { address_component }
    var formattedAddresses: TencentFormattedAddresses? { formatted_addresses }
}

struct TencentAddressComponent: Codable {
    let nation: String?
    let province: String?
    let city: String?
    let district: String?
    let town: String?
    let street: String?
    let street_number: String?
}

struct TencentFormattedAddresses: Codable {
    let recommend: String?
    let rough: String?
    let standard_address: String?
    
    // 计算属性，保持向后兼容
    var regular: String? { standard_address }
}

struct TencentPOI: Codable {
    let title: String?
    let address: String?
    let category: String?
}

// MARK: - String扩展，添加MD5计算
extension String {
    var md5: String {
        let data = Data(self.utf8)
        var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
        _ = data.withUnsafeBytes {
            CC_MD5($0.baseAddress, CC_LONG(data.count), &digest)
        }
        return digest.map { String(format: "%02hhx", $0) }.joined()
    }
}

// MARK: - 异步扩展方法
extension TencentMapsService {
    /// 获取地址信息（异步），用于统一接口
    func fetchAddressInfoAsync(coordinate: CLLocationCoordinate2D) async -> GlobalLocationAddressInfo? {
        print("[\(Date())] \(#function) called with coordinate: \(coordinate)")
        
        // 优先尝试带签名的请求
        if let result = await reverseGeocodeWithSignature(coordinate: coordinate) {
            return result
        }
        
        // 如果签名请求失败，尝试普通请求
        return await reverseGeocode(coordinate: coordinate)
    }
} 